﻿/***********************************************************************************************************************
* DISCLAIMER
* This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products.
* No other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all
* applicable laws, including copyright laws. 
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING THIS SOFTWARE, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT.  ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY
* LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE FOR ANY DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR
* ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability 
* of this software. By using this software, you agree to the additional terms and conditions found by accessing the 
* following link:
* http://www.renesas.com/disclaimer
*
* Copyright (C) 2018, 2022 Renesas Electronics Corporation. All rights reserved.
***********************************************************************************************************************/

/***********************************************************************************************************************
* File Name        : Config_UART0_user.c
* Component Version: 1.5.0
* Device(s)        : R7F702300EABA
* Description      : This file implements device driver for Config_UART0.
***********************************************************************************************************************/
/***********************************************************************************************************************
Pragma directive
***********************************************************************************************************************/
/* Start user code for pragma. Do not edit comment generated here */
/* End user code. Do not edit comment generated here */

/***********************************************************************************************************************
Includes
***********************************************************************************************************************/
#include "r_cg_macrodriver.h"
#include "r_cg_userdefine.h"
#include "Config_UART0.h"
/* Start user code for include. Do not edit comment generated here */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "ringbuffer.h"
/* End user code. Do not edit comment generated here */

/***********************************************************************************************************************
Global variables and functions
***********************************************************************************************************************/
extern volatile uint8_t  * gp_uart0_tx_address;       /* uart0 transmit data address */
extern volatile uint16_t   g_uart0_tx_count;          /* uart0 transmit data number */
extern volatile uint8_t  * gp_uart0_rx_address;       /* uart0 receive data address */
extern volatile uint16_t   g_uart0_rx_count;          /* uart0 receive data number */
extern volatile uint16_t   g_uart0_rx_length;         /* uart0 receive data length */
void r_Config_UART0_callback_receiveend(void);
void r_Config_UART0_callback_sendend(void);
void r_Config_UART0_callback_error(uint32_t err_type);
/* Start user code for global. Do not edit comment generated here */
volatile uint8_t transmitend_flag_0 = 0;
volatile uint8_t receiveend_flag_0 = 0;
uint8_t print_buf[64];
uint32_t u32State = 0x00000000;
uint32_t u32WaitTickCount = 0x00000000;

struct ringbuffer uart0_rx_rb;
uint8_t *pbuf_uart0_rx_rb = NULL;

struct ringbuffer uart0_tx_rb;
uint8_t *pbuf_uart0_tx_rb = NULL;

#define USE_UART0_TX_DMA 1
#define USE_UART0_RX_DMA 0
/* End user code. Do not edit comment generated here */

/***********************************************************************************************************************
* Function Name: R_Config_UART0_Create_UserInit
* Description  : This function adds user code after initializing UART module.
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/

void R_Config_UART0_Create_UserInit(void)
{
    /* Start user code for user init. Do not edit comment generated here */
    if (pbuf_uart0_rx_rb == NULL)
    {
        pbuf_uart0_rx_rb = malloc(1024);
    }
    ringbuffer_init(&uart0_rx_rb, pbuf_uart0_rx_rb, 1024);
    
    if (pbuf_uart0_tx_rb == NULL)
    {
        pbuf_uart0_tx_rb = malloc(1024);
    }
    ringbuffer_init(&uart0_tx_rb, pbuf_uart0_tx_rb, 1024);
    /* End user code. Do not edit comment generated here */
}

/***********************************************************************************************************************
* Function Name: r_Config_UART0_interrupt_receive
* Description  : This function is UART0 receive interrupt service routine.
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/
#pragma interrupt r_Config_UART0_interrupt_receive(enable=false, channel=418, fpu=true, callt=false)
void r_Config_UART0_interrupt_receive(void)
{
#if 0
    uint8_t  rx_data_8;
    uint16_t temp;
    rx_data_8 = RLIN30.LURDR.UINT16;

    temp = g_uart0_rx_count;
    if (g_uart0_rx_length > temp)
    {
        *gp_uart0_rx_address = rx_data_8;
        gp_uart0_rx_address++;
        g_uart0_rx_count++;
        temp = g_uart0_rx_count;
        if (g_uart0_rx_length == temp)
        {
            r_Config_UART0_callback_receiveend();
        }
    }
#else
    uint8_t  rx_data_8;
    rx_data_8 = RLIN30.LURDR.UINT16;
    if (0 == ringbuffer_putchar(&uart0_rx_rb, rx_data_8))
    {
        ringbuffer_putchar_force(&uart0_rx_rb, rx_data_8);
    }
#endif
}

/***********************************************************************************************************************
* Function Name: r_Config_UART0_interrupt_error
* Description  : This function is UART0 error interrupt service routine.
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/
#pragma interrupt r_Config_UART0_interrupt_error(enable=false, channel=419, fpu=true, callt=false)
void r_Config_UART0_interrupt_error(void)
{
    uint32_t err_type;
    *gp_uart0_rx_address = RLIN30.LURDR.UINT16;
    err_type = (uint8_t)(RLIN30.LEST);
    RLIN30.LEST &= (uint8_t) ~_UART_CLEAR_ERROR_FLAG;
    r_Config_UART0_callback_error(err_type);
}

/***********************************************************************************************************************
* Function Name: r_Config_UART0_interrupt_send
* Description  : This function is UART0 send interrupt service routine.
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/
#pragma interrupt r_Config_UART0_interrupt_send(enable=false, channel=417, fpu=true, callt=false)
void r_Config_UART0_interrupt_send(void)
{
    if (g_uart0_tx_count > 0U)
    {
        RLIN30.LUTDR.UINT16= *gp_uart0_tx_address;
        gp_uart0_tx_address++;
        g_uart0_tx_count--;
    }
    else
    {
        r_Config_UART0_callback_sendend();
    }
}

/***********************************************************************************************************************
* Function Name: r_Config_UART0_callback_sendend
* Description  : This function is UART0 send end callback service routine.
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/
void r_Config_UART0_callback_sendend(void)
{
    /* Start user code for r_Config_UART0_callback_sendend. Do not edit comment generated here */
    transmitend_flag_0 = 1;
    /* End user code. Do not edit comment generated here */
}

/***********************************************************************************************************************
* Function Name: r_Config_UART0_callback_error
* Description  : This function is UART0 error callback service routine.
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/
void r_Config_UART0_callback_error(uint32_t err_type)
{
    /* Start user code for r_Config_UART0_callback_error. Do not edit comment generated here */
    NOP();
    /* End user code. Do not edit comment generated here */
}

/***********************************************************************************************************************
* Function Name: r_Config_UART0_callback_receiveend
* Description  : This function is UART0 receive end callback service routine.
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/
void r_Config_UART0_callback_receiveend(void)
{
    /* Start user code for r_Config_UART0_callback_receiveend. Do not edit comment generated here */
    receiveend_flag_0 = 1;
    /* End user code. Do not edit comment generated here */
}

/* Start user code for adding. Do not edit comment generated here */
typedef enum UART0_TX_STATE
{
    eUart0TxInit = 0x00000001,
    eUart0Tx = 0x00000002,
    eUart0TxWaitEnd = 0x00000004,
    eUart0TestTx = 0x80000000,
    eUart0TxIdle = 0x0000FFFF
} E_UART0_TX_STATE;

typedef enum UART0_RX_STATE
{
    eUart0RxInit = 0x00000001,
    eUart0Rx = 0x00000002,
    eUart0RxWaitEnd = 0x00000004,
    eUart0TxOneByteForDmaStartWaitEnd = 0x00000008,
    eUart0TxDmaWaitEnd = 0x00000010,
    eUart0TestRx = 0x80000000,
    eUart0RxIdle = 0x0000FFFF
} E_UART0_RX_STATE;

void Uart0Proc(uint32_t u32Cmd, uint32_t u32Tick)
{
    static char * strtmp = NULL;
    static uint32_t sTxState = 0x00000000;
    static uint32_t sTxWaitTickCount = 0x00000000;
    static uint32_t sRxState = 0x00000000;
    static uint32_t sRxWaitTickCount = 0x00000000;
    
    static E_UART0_TX_STATE eUart0TxState = eUart0Tx;
    static E_UART0_RX_STATE eUart0RxState = eUart0Rx;

_TX:
    if (sTxWaitTickCount > 0)
    {
        sTxWaitTickCount--; //未到时间
        goto _RX;
    }
    
    switch(eUart0TxState)
    {
        case eUart0TxInit:
            break;
        case eUart0Tx:
        {
            uint32_t u32DataLen = ringbuffer_data_len(&uart0_tx_rb);
            if (u32DataLen > 0)
            {
                unsigned int u32Temp;
                if (strtmp != NULL)
                {
                    free(strtmp);
                    strtmp = NULL;
                }
                strtmp = (char *)(void *)malloc(u32DataLen);
                u32Temp = ringbuffer_get(&uart0_tx_rb, strtmp, u32DataLen);
                if (u32Temp != u32DataLen)
                {
                    //some error may be  occur!
                }
#if USE_UART0_TX_DMA
                if (u32DataLen > 1)
                {
                     R_Config_SDMAC00_Reconfigure(strtmp + 1, (uint32_t)&RLIN30.LUTDR.UINT16, u32DataLen - 1);
#if 1
                    if(MD_OK == R_Config_UART0_Send((uint8_t * const) strtmp, 1))
                    {
                        sTxState = eUart0TxOneByteForDmaStartWaitEnd;
                        sTxWaitTickCount = 0;
                    }
#endif
                    sTxWaitTickCount = 0;
                }
#else
                if(MD_OK == R_Config_UART0_Send((uint8_t * const) strtmp, u32DataLen))
                {
                    sTxState = eUart0TxWaitEnd;
                    sTxWaitTickCount = 0;
                }
#endif
            }
        }
            break;
        case eUart0TxWaitEnd:
            if (1 == transmitend_flag_0)
            {
                if (strtmp != 0)
                {
                    free(strtmp);
                    strtmp = 0;
                }
                sTxState = eUart0Tx;
                sTxWaitTickCount = 0;
            }
            break;
        case eUart0TxOneByteForDmaStartWaitEnd:
            if (1 == transmitend_flag_0)
            {
                if (strtmp != 0)
                {
                    free(strtmp);
                    strtmp = 0;
                }
                sTxState = eUart0TxDmaWaitEnd;
                sTxWaitTickCount = 0;
            }
            break;
        case eUart0TxDmaWaitEnd:
            if (1 == transmitend_flag_0)
            {
                if (strtmp != 0)
                {
                    free(strtmp);
                    strtmp = 0;
                }
                sTxState = eUart0Tx;
                sTxWaitTickCount = 0;
            }
            break;
        case eUart0TestTx:
            switch(sTxState)
            {
                case 0:
                    if (strtmp == 0)
                    {
                        strtmp = (char *)(void *)malloc(64);
                    }
                    else
                    {
                        //
                    }
                    sprintf((char *)strtmp, "tick = %d\r\n", u32Tick);
                    transmitend_flag_0 = 0;
                    if(MD_OK == R_Config_UART0_SendString((uint8_t * const) strtmp))
                    {
                        sTxState = 1;
                        sTxWaitTickCount = 0;
                    }
                    break;
                case 1:
                    while(transmitend_flag_0 != 1);
                    if (strtmp != 0)
                    {
                        free(strtmp);
                        strtmp = 0;
                    }
                    sTxState = 0;
                    sTxWaitTickCount = 0;
                    break;
                default:
                break;
            }
            break;
        case eUart0TxIdle:
            break;
        default:
            break;
    }

_RX:
    if (sRxWaitTickCount > 0)
    {
        sRxWaitTickCount--; //未到时间
        goto _EXIT;
    }
    
    switch(eUart0RxState)
    {
        case eUart0RxInit:
            break;
        case eUart0Rx:
        {
            //数据在中断中接收
            uint32_t u32DataLen = ringbuffer_data_len(&uart0_rx_rb);
            if (u32DataLen > 0)
            {
                unsigned int u32Temp;
                char * rx_buf = (char *)(void *)malloc(u32DataLen);
                u32Temp = ringbuffer_get(&uart0_rx_rb, rx_buf, u32DataLen);
                if (u32Temp != u32DataLen)
                {
                    //some error may be  occur!
                }
                PrintText(rx_buf, u32DataLen);
                free(rx_buf);
                rx_buf = 0;
            }
        }
            break;
        case eUart0RxWaitEnd:
            if (1 == transmitend_flag_0)
            {
                if (strtmp != 0)
                {
                    free(strtmp);
                    strtmp = 0;
                }
                sTxState = eUart0Tx;
                sTxWaitTickCount = 0;
            }
            break;
        case eUart0RxIdle:
            break;
        default:
            break;
    }

_EXIT:
}

MD_STATUS PrintText(uint8_t * pbuf, uint16_t len)
{
    uint32_t u32Temp = 0;

    u32Temp = ringbuffer_put(&uart0_tx_rb, pbuf, len);
    if (u32Temp != len)
    {
        u32Temp = ringbuffer_put_force(&uart0_tx_rb, pbuf, len);
    }
    
    return MD_OK;
}
/* End user code. Do not edit comment generated here */
